# coding:utf-8
from PySide6 import QtCore
from PySide6.QtCore import Slot, QTimer, Signal
from PySide6.QtWidgets import QWidget
import serial.tools.list_ports #windows 下
from APP.HYB01Power.Handle.serialHYB01Powerhandle import SerialHYB01PowerHandle
from Util.util import HexToStrOnTime, BytesToStrOnTime, get_s16
from APP.HYB01Power.SendData.SendHYB01PowerData import SendHYB01PowerCode
from APP.HYB01Power.UI.HYB01PowerForm import Ui_HYB01PowerTest
import re

from qfluentwidgets import TeachingTip, TeachingTipTailPosition, InfoBarIcon


class FocusInterface_HYB01Power(QWidget, Ui_HYB01PowerTest):
    ThemeSignal = Signal(int)  # 0: 跟随系统; 1: 明亮; 2: 暗黑

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.setupUi(self)
        plist = list(serial.tools.list_ports.comports())  # Window下
        # plist = glob.glob('/dev/tty[A-Za-z]*')  #Linux下
        self.m_SerialsComboList = []
        if len(plist) <= 0:
            # print(u'没有发现端口！')
            pass
        else:
            for plist1 in plist:  # Windows
                plist2 = list(plist1)  # Windows
                self.m_SerialsComboList.append(plist2[1])  # Windows
            # self.m_SerialsComboList = plist[0]            #Linux
        # print(self.m_SerialsComboList)
        self.SerialCombo_box.addItems(self.m_SerialsComboList)
        self.serialHandle = SerialHYB01PowerHandle()
        self.serialHandle.EventHYB01PowerSignal.connect(self.EventSlot)  # type: ignore
        self.SerialCombo_box.currentTextChanged['QString'].connect(
            self.OnSelectCom)
        self.OpenSerial_pribtn.clicked.connect(self.OnOpenComPressed)  # type: ignore
        self.ClearTx_pribtn.clicked.connect(self.OnClearTxData)  # type: ignore
        self.ClearRx_pribtn.clicked.connect(self.OnClearRxData)  # type: ignore
        self.serialHandle.HYB01PowerReceiveDataSignal.connect(self.DataReceiveSlot)  # type: ignore
        self.QBRunTime = 100
        self.SBRunTime = 100
        self.QBPwm = 50
        self.SBPwm = 50
        self.HDPwm = 50

        self.QBRunTimeLEdit.setInputMethodHints(QtCore.Qt.InputMethodHint.ImhDigitsOnly)
        self.QBRunTimeLEdit.editingFinished.connect(self.OnQBRunTimeChanged)

        self.SBRunTimeLEdit.setInputMethodHints(QtCore.Qt.InputMethodHint.ImhDigitsOnly)
        self.SBRunTimeLEdit.editingFinished.connect(self.OnSBRunTimeChanged)

        self.QBPwmLEdit.setInputMethodHints(QtCore.Qt.InputMethodHint.ImhDigitsOnly)
        self.QBPwmLEdit.editingFinished.connect(self.OnQBPwmChanged)

        self.SBPwmLEdit.setInputMethodHints(QtCore.Qt.InputMethodHint.ImhDigitsOnly)
        self.SBPwmLEdit.editingFinished.connect(self.OnSBPwmChanged)

        self.HDPwmLedit.setInputMethodHints(QtCore.Qt.InputMethodHint.ImhDigitsOnly)
        self.HDPwmLedit.editingFinished.connect(self.OnHDPwmChanged)

        self.SingleFrameSendPriBtn.clicked.connect(self.SendData)  # type: ignore

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.SendData)

        self.CycleSendSBtn.checkedChanged.connect(self.AutoSend)





    def showBottomTip(self, Target, message):
        TeachingTip.create(
            target=Target,
            icon=InfoBarIcon.ERROR,
            title='提示：',
            content=message,
            isClosable=True,
            tailPosition=TeachingTipTailPosition.TOP,
            duration=2000,
            parent=self
        )

    @Slot(bool)
    def EventSlot(self, message):
        if message:
            self.OpenSerial_pribtn.setText(u'关闭串口')
        else:
            self.OpenSerial_pribtn.setText(u'打开串口')
        pass

    @Slot(str)
    def OnSelectCom(self, message):
        # print("选择了" + message)
        pass

    @Slot()
    def OnOpenComPressed(self):
        # print(u'pressed')

        if not self.serialHandle.openSerialPort(self.SerialCombo_box.currentText()):
            self.showBottomTip(self.OpenSerial_pribtn, u'当前端口已被占用，或存在问题，无法打开！')
        pass

    @Slot()
    def OnClearTxData(self):
        self.SendDataPlainTextEdit.clear()
        pass

    @Slot()
    def OnClearRxData(self):
        self.RecvDataPlainTextEdit.clear()
        pass

    @Slot(list)
    def DataReceiveSlot(self, message):
        self.RecvDataPlainTextEdit.appendPlainText(HexToStrOnTime(message).upper())
        if (message[2] & 0x08) == 0x08:
            self.BreakStateLabel.setText(u'已刹车')
        else:
            self.BreakStateLabel.setText(u'未刹车')

        if (message[3] & 0x80) == 0x80:
            self.XingJin1StateLabel.setText(u'行进1:合闸')
        else:
            self.XingJin1StateLabel.setText(u'行进1:分闸')

        if (message[3] & 0x40) == 0x40:
            self.XingJin2StateLabel.setText(u'行进2:合闸')
        else:
            self.XingJin2StateLabel.setText(u'行进2:分闸')

        if (message[3] & 0x20) == 0x20:
            self.XingJin3StateLabel.setText(u'行进3:合闸')
        else:
            self.XingJin3StateLabel.setText(u'行进3:分闸')

        if (message[3] & 0x08) == 0x08:
            self.JxbStateLabel.setText(u'机械臂:合闸')
        else:
            self.JxbStateLabel.setText(u'机械臂:分闸')

        if (message[3] & 0x04) == 0x04:
            self.BenTiStateLabel.setText(u'车体:合闸')
        else:
            self.BenTiStateLabel.setText(u'车体:分闸')

        QBRunTime = float((message[4] * 256 + message[5]) / 100.0)
        self.QBRunTimeStateLabel.setText(u'气泵开启时间: ' + format(QBRunTime, ".2f") + u's')
        self.QBPowerStateLabel.setText(u'气泵占空比: ' + str(message[6]) + u'%')

        SBRunTime = float((message[7] * 256 + message[8]) / 100.0)
        self.SBRunTimeStateLabel.setText(u'水泵开启时间: ' + format(SBRunTime, ".2f") + u's')
        self.SBPowerStateLabel.setText(u'水泵占空比: ' + str(message[9]) + u'%')
        self.HDPowerStateLabel.setText(u'涵道电机占空比: ' + str(message[10]) + u'%')

        if (message[11] & 0x80) == 0x80:
            self.QBTriStateLabel.setText(u'气泵: 触发')
        else:
            self.QBTriStateLabel.setText(u'气泵: 未触发')

        if (message[11] & 0x40) == 0x40:
            self.SBTriStateLabel.setText(u'水泵: 触发')
        else:
            self.SBTriStateLabel.setText(u'水泵: 未触发')

        if (message[11] & 0x20) == 0x20:
            self.HDTriStateLabel.setText(u'涵道电机: 运行')
        else:
            self.HDTriStateLabel.setText(u'涵道电机: 停止')

        if (message[12] & 0xF0) == 0xF0:
            self.EmStateLabel.setText(u'急停')
        else:
            self.EmStateLabel.setText(u'未急停')

        if (message[12] & 0x0F) == 0x0F:
            self.OpenCloseStateLabel.setText(u'关机')
        else:
            self.OpenCloseStateLabel.setText(u'开机')

        LeftDianLiang = float((message[13] * 256 + message[14]) / 10.0)
        self.LElectricityStateLabel.setText(u'左电量: ' + str(LeftDianLiang) + u'%')
        RightDianLiang = float((message[33] * 256 + message[34]) / 10.0)
        self.RElectricityStateLabel.setText(u'右电量: ' + str(RightDianLiang) + u'%')

        LeftCV = float(((message[15] * 16777216) + (message[16] * 65536) + (message[17] * 256) + message[18]) / 1000.0)
        self.LVoltageStateLabel.setText(u'左电压: ' + str(LeftCV) + u'V')
        RightCV = float(((message[35] * 16777216) + (message[36] * 65536) + (message[37] * 256) + message[38]) / 1000.0)
        self.RVoltageStateLabel.setText(u'右电压: ' + str(RightCV) + u'V')

        LeftCC = float(((message[19] * 16777216) + (message[20] * 65536) + (message[21] * 256) + message[22]) / 1000.0)
        self.LCurrentStateLabel.setText(u'左电流: ' + str(LeftCC) + u'A')
        RightCC = float(((message[39] * 16777216) + (message[40] * 65536) + (message[41] * 256) + message[42]) / 1000.0)
        self.RCurrentStateLabel.setText(u'右电流: ' + str(RightCC) + u'A')

        LeftMaxTemp = float(get_s16((message[23] * 256) + message[24]) / 10.0)
        self.LMaxtmpStateLabel.setText(u'左最高温度: ' + str(LeftMaxTemp) + u'℃')
        RightMaxTemp = float(get_s16((message[43] * 256) + message[44]) / 10.0)
        self.RMaxtmpStateLabel.setText(u'右最高温度: ' + str(RightMaxTemp) + u'℃')

        LeftMinTemp = float(get_s16((message[25] * 256) + message[26]) / 10.0)
        self.LMintmpStateLabel.setText(u'左最低温度: ' + str(LeftMinTemp) + u'℃')
        RightMinTemp = float(get_s16((message[45] * 256) + message[46]) / 10.0)
        self.RMintmpStateLabel.setText(u'右最低温度: ' + str(RightMinTemp) + u'℃')

        LSingleMaxV = float(((message[27] * 256) + message[28]) / 1000.0)
        self.LSingleMaxVoltageStateLabel.setText(u'左单体最高电压: ' + str(LSingleMaxV) + u'V')
        RSingleMaxV = float(((message[47] * 256) + message[48]) / 1000.0)
        self.RSingleMaxVoltageStateLabel.setText(u'右单体最高电压: ' + str(RSingleMaxV) + u'V')

        LSingleMinV = float(((message[29] * 256) + message[30]) / 1000.0)
        self.LSingleMinVoltageStateLabel.setText(u'左单体最低电压: ' + str(LSingleMinV) + u'V')
        RSingleMinV = float(((message[49] * 256) + message[50]) / 1000.0)
        self.RSingleMinVoltageStateLabel.setText(u'右单体最低电压: ' + str(RSingleMinV) + u'V')

        LCycles = message[31] * 256 + message[32]
        self.LCyclesStateLabel.setText(u'左循环次数: ' + str(LCycles))
        RCycles = message[51] * 256 + message[52]
        self.RCyclesStateLabel.setText(u'右循环次数: ' + str(RCycles))
        pass


    @Slot()
    def OnQBRunTimeChanged(self):
        text = self.QBRunTimeLEdit.text()
        if self.is_positive_integer(text):
            value = int(text)
            if value >= 1 and value <= 65535:
                self.QBRunTime = value
            else:
                self.showBottomTip(self.QBRunTimeLEdit, u'请输入正整数数字! 输入范围(1 ~ 65535)')
                self.QBRunTimeLEdit.setText(str(self.QBRunTime))
        else:
            self.showBottomTip(self.QBRunTimeLEdit, u'请输入正整数数字! 输入范围(1 ~ 65535)')
            self.QBRunTimeLEdit.setText(str(self.QBRunTime))

    @Slot()
    def OnSBRunTimeChanged(self):
        text = self.SBRunTimeLEdit.text()
        if self.is_positive_integer(text):
            value = int(text)
            if value >= 1 and value <= 65535:
                self.SBRunTime = value
            else:
                self.showBottomTip(self.SBRunTimeLEdit, u'请输入正整数数字! 输入范围(1 ~ 65535)')
                self.SBRunTimeLEdit.setText(str(self.SBRunTime))
        else:
            self.showBottomTip(self.SBRunTimeLEdit, u'请输入正整数数字! 输入范围(1 ~ 65535)')
            self.SBRunTimeLEdit.setText(str(self.SBRunTime))

    @Slot()
    def OnQBPwmChanged(self):
        text = self.QBPwmLEdit.text()
        if self.is_integer(text):
            value = int(text)
            if value >= 0 and value <= 100:
                self.QBPwm = value
            else:
                self.showBottomTip(self.QBPwmLEdit, u'请输入整数数字! 输入范围(0 ~ 100)')
                self.QBPwmLEdit.setText(str(self.QBPwm))
        else:
            self.showBottomTip(self.QBPwmLEdit, u'请输入整数数字! 输入范围(0 ~ 100)')
            self.QBPwmLEdit.setText(str(self.QBPwm))

    @Slot()
    def OnSBPwmChanged(self):
        text = self.SBPwmLEdit.text()
        if self.is_integer(text):
            value = int(text)
            if value >= 0 and value <= 100:
                self.SBPwm = value
            else:
                self.showBottomTip(self.SBPwmLEdit, u'请输入整数数字! 输入范围(0 ~ 100)')
                self.SBPwmLEdit.setText(str(self.SBPwm))
        else:
            self.showBottomTip(self.SBPwmLEdit, u'请输入整数数字! 输入范围(0 ~ 100)')
            self.SBPwmLEdit.setText(str(self.SBPwm))

    @Slot()
    def OnHDPwmChanged(self):
        text = self.HDPwmLedit.text()
        if self.is_integer(text):
            value = int(text)
            if value >= 0 and value <= 100:
                self.HDPwm = value
            else:
                self.showBottomTip(self.HDPwmLedit, u'请输入整数数字! 输入范围(0 ~ 100)')
                self.HDPwmLedit.setText(str(self.HDPwm))
        else:
            self.showBottomTip(self.HDPwmLedit, u'请输入整数数字! 输入范围(0 ~ 100)')
            self.HDPwmLedit.setText(str(self.HDPwm))

    @Slot()
    def SendData(self):
        if self.BreakSBtn.isChecked():
            breakCode = 0x08
        else:
            breakCode = 0x00
        KongKaiCode = 0x00
        if self.XingJin1SBtn.isChecked():
            KongKaiCode = KongKaiCode | 0x80
        if self.XingJin2SBtn.isChecked():
            KongKaiCode = KongKaiCode | 0x40
        if self.XingJin3SBtn.isChecked():
            KongKaiCode = KongKaiCode | 0x20
        if self.JxbSBtn.isChecked():
            KongKaiCode = KongKaiCode | 0x08

        triRunCode = 0x00
        if self.QBTriSBtn.isChecked():
            triRunCode = triRunCode | 0x80
        if self.SBTriSBtn.isChecked():
            triRunCode = triRunCode | 0x40
        if self.HDControlSBtn.isChecked():
            triRunCode = triRunCode | 0x20


        TxDataBuffer = SendHYB01PowerCode(breakCode, KongKaiCode, self.QBRunTime, self.QBPwm, self.SBRunTime, self.SBPwm, self.HDPwm, triRunCode)
        self.serialHandle.SendFrame(TxDataBuffer)
        self.SendDataPlainTextEdit.appendPlainText(BytesToStrOnTime(TxDataBuffer).upper())

    def is_positive_integer(self, s):
        return bool(re.match(r'^[1-9]\d*$', s))

    def is_integer(self, s):
        return bool(re.match(r'^-?\d+$', s))

    @Slot()
    def AutoSend(self):
        if self.CycleSendSBtn.isChecked():
            self.timer.start(100)
            pass
        else:
            self.timer.stop()
            pass
        pass

    def closeEvent(self, a0):
        self.timer.stop()
        self.serialHandle.closeSerialPort()
        pass
